Skip to content

Add macOS (Apple silicon) support - #11

Open
BKPepe wants to merge 3 commits into
GeorgeSapkin:mainfrom
BKPepe:macos-support
Open

BKPepe wants to merge 3 commits into
GeorgeSapkin:mainfrom
BKPepe:macos-support

Conversation

@BKPepe

@BKPepe BKPepe commented Aug 5, 2026

Copy link
Copy Markdown

Summary

This makes Bouwer build and run on macOS and fills in the missing macOS metadata, tested end-to-end on real hardware — the README said there was no practical way to test macOS, so hopefully this helps:

  • build: add slint dependency for macOS — slint was only declared for Linux/Windows targets, so i-slint-backend-winit compiled without any renderer feature on macOS and the build failed. Adds a macOS target section mirroring the Linux one (winit backend + Skia renderer).
  • feat: embed Info.plist on macOS — as a bare (unbundled) binary, the About panel showed no name, version or copyright. build.rs now generates an Info.plist from CARGO_PKG_VERSION and links it into the __TEXT,__info_plist section — the macOS counterpart of the winresource metadata on Windows. The About panel now shows name, version, copyright and the project URL, and CFBundleName fixes the app menu title to "Bouwer".
  • docs: mark macOS on Apple silicon as supported — documents Podman socket setup on macOS and updates the supported-platforms paragraph.

Testing

Verified on macOS 26.5.2, Apple silicon (arm64), Rust 1.97.1, Podman 6.0.2 (podman machine), Bouwer 0.3.0:

  • cargo check / cargo build pass (they fail on main without the Cargo.toml change).
  • Engine detection works with DOCKER_HOST pointing at the Podman machine socket; version and profile metadata load, cache and config land in ~/Library/Caches/bouwer and ~/Library/Application Support/bouwer.
  • Downloaded the openwrt/imagebuilder:mvebu-cortexa9-25.12.5 image (1.92 GB) from the app and built firmware for the CZ.NIC Turris Omnia profile — all output images produced and sha256sums verify OK; the build container is cleaned up afterwards.
  • About panel verified visually and via the accessibility tree ("Bouwer", "Version 0.3.0", copyright + URL).

Known remaining gaps on macOS

  • Containers::new only probes Linux-style Podman socket paths, so without podman-mac-helper or DOCKER_HOST/CONTAINER_HOST the Podman machine socket ($TMPDIR/podman/podman-machine-default-api.sock) is not found. Happy to send a follow-up PR adding that path to the detection if you want.
  • The Finder/Dock icon stays generic — that would need a proper .app bundle, which felt like a bigger decision than this PR should make.

🤖 Generated with Claude Code

Copilot AI lite review requested due to automatic review settings August 5, 2026 10:34

This comment was marked as low quality.

@GeorgeSapkin

Copy link
Copy Markdown
Owner

Thanks for the initiative.

I think the Podman/Docker socket detection should come first: either as part of this PR or as a separate one, if this PR is strictly packaging-focused. Either way works for me.

And I do think mac apps should use the proper packaging - be it app or dmg - whichever is more appropriate. I did the whole packaging thing before, but couldn't test the Podman part with nested virtualization, and put it on hold.

Comment thread Cargo.toml Resolved
@BKPepe
BKPepe force-pushed the macos-support branch 2 times, most recently from 3862219 to 5eacd1d Compare August 12, 2026 09:30
BKPepe and others added 3 commits August 13, 2026 15:44
The slint crate was only declared for Linux and Windows targets, so on
macOS i-slint-backend-winit compiled without any renderer feature and
the build failed. Fold macOS into the shared native slint target
(winit backend with the Skia renderer).

Embed an Info.plist generated from CARGO_PKG_VERSION into the
__TEXT,__info_plist section of the binary so the About panel shows the
application name, version, copyright and project URL without an .app
bundle, the macOS counterpart of the winresource metadata on Windows.

Detect the default Podman machine API socket in $TMPDIR so a running
Podman machine is found without DOCKER_HOST or the Podman system
helper; DOCKER_HOST, CONTAINER_HOST and the Docker socket defaults
still apply otherwise.

Verified end-to-end on macOS 26 (arm64) with Podman: engine
autodetection, image builder download and a firmware build for
mvebu/cortexa9.

Co-Authored-By: George Sapkin <george@sapk.in>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Document the container engine setup on macOS (automatic detection of
the default Podman machine socket, DOCKER_HOST for custom setups) and
that image builder images live inside the Podman/Docker VM there, as
on Windows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add macos-latest (Apple silicon) to the build matrix and package the
binary as a macos-aarch64 release asset. Unlike Linux and Windows, the
binary is not compressed with upx: UPX-packed Mach-O binaries are not
reliable on modern macOS; the release profile already strips symbols.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@GeorgeSapkin

Copy link
Copy Markdown
Owner

Rebased. I'm slowly looking through my old macOS support implementation, so I'll add some questions as I think of them.

Does it make sense to add/test x86/64 support? I did this before:

    strategy:
      matrix:
        include:
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact: bouwer-macos-latest-aarch64
          - os: macos-latest
            target: x86_64-apple-darwin
            artifact: bouwer-macos-latest-x86_64
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            artifact: bouwer-ubuntu-latest
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact: bouwer-windows-latest

This is what I had for dmg support:

      - name: Package macOS
        if: matrix.os == 'macos-latest'
        run: |
          cargo install cargo-packager --locked
          cargo packager --release --formats dmg --target ${{ matrix.target }}

and then including in the upload, of course:

      - name: Upload binary
        uses: actions/upload-artifact@v7
        with:
          name: ${{ matrix.artifact }}
          path: |
            target/${{ matrix.target }}/release/bouwer
            target/${{ matrix.target }}/release/bouwer.exe
            target/${{ matrix.target }}/release/packager/**/*.dmg
          if-no-files-found: error

and:

      - name: Create GitHub release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            dist/*.dmg
            dist/*.tar.gz
            dist/*.zip
          generate_release_notes: true

IDK, which metadata goes where, but I only see this in my old implementation, i.e. no plist stuff:

[package.metadata.packager]
name = "Bouwer"
identifier = "in.sapk.bouwer"
icon = ["assets/logo.png"]
resources = ["LICENSE"]

[package.metadata.packager.macos]
minimum_system_version = "11.0"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants